package com.cloud.common.utils;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.math.BigInteger;
import java.security.MessageDigest;

/**
 * MD5加密工具类
 * MessageDigest:提供信息摘要算法的功能,如MD5或SHA算法;非单实例的;抽象类,扩展MessageDigesSpi
 * 通过getInstance系列静态函数来进行实例化和初始化
 * update():处理数据
 * reset():重置摘要.无论什么时候都可以调用
 * digest():返回结果.被调用后MessageDigest会被还原成初始状态
 * https://www.cnblogs.com/mengfanrong/p/3896447.html
 */
public class MD5Util {

    private static final Logger logger = LoggerFactory.getLogger(MD5Util.class);

    private static final String ALGORITHM_NAME = "MD5";

    private static final String CHARSET_NAME = "UTF-8";

    private MD5Util() {
    }

    /**
     * 对字符串MD5无盐值加密
     *
     * @param plain 要加密的字符串
     * @return 经过MD5加密的32位字符串(小写字母 + 数字)
     */
    public static String MD5Lower(String plain) {
        return MD5Lower(plain, null);
    }

    /**
     * 对字符串MD5有盐加密
     *
     * @param plain 要加密的字符串
     * @param salt  要加入的盐值
     * @return 经过MD5加密的32位字符串(小写字母 + 数字)
     */
    public static String MD5Lower(String plain, String salt) {
        try {
            //算法名不区分大小写
            MessageDigest md = MessageDigest.getInstance(ALGORITHM_NAME);
            md.update(plain.getBytes(CHARSET_NAME));
            if (salt != null) {
                md.update(salt.getBytes(CHARSET_NAME));
            }
            return new BigInteger(1, md.digest()).toString(16);
        } catch (Exception e) {
            logger.error("MD5加密出错:" + e.toString());
            return null;
        }
    }

    /**
     * 对字符串MD5无盐值加密
     *
     * @param plain 要加密的字符串
     * @return 经过MD5加密的32位字符串(大写字母 + 数字)
     */
    public static String MD5Upper(String plain) {
        return MD5Upper(plain, null);
    }

    /**
     * 对字符串MD5有盐加密
     *
     * @param plain 要加密的字符串
     * @param salt  要加入的盐值
     * @return 经过MD5加密的32位字符串(大写字母 + 数字)
     */
    public static String MD5Upper(String plain, String salt) {
        String md5 = MD5Lower(plain, salt);
        if (md5 != null) {
            md5 = md5.toUpperCase();
        }
        return md5;
    }

    /**
     * 校验MD5码
     *
     * @param plain 源码
     * @param md5   要比较的MD5码
     * @return 是否相同
     */
    public static boolean MD5equals(String plain, String md5) {
        return MD5equals(plain, null, md5);
    }

    /**
     * 校验MD5码
     *
     * @param plain 源码
     * @param salt  要加入的盐值
     * @param md5   要比较的MD5码
     * @return 是否相同
     */
    public static boolean MD5equals(String plain, String salt, String md5) {
        return md5.equals(MD5Upper(plain, salt)) || md5.equals(MD5Lower(plain, salt));
    }
}
